package com.fiberhome.sdmp.xmlcomparator;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/**
 * Hello world!
 * 
 */
public class App {
	public static void main(String[] args) throws IOException, DocumentException {
		String projectPath = App.class.getProtectionDomain().getCodeSource().getLocation().getPath();

		File folder = new File(projectPath);
		System.out.println("你的当前工作目录是: " + folder.getAbsolutePath() + Cons.R_N);

		List<File> displayFileList = new LinkedList<File>();

		File[] fileList = folder.listFiles();
		for (File file : fileList) {
			if (!file.isDirectory() && (file.getName().endsWith("xsd") || file.getName().endsWith("xml"))) {
				displayFileList.add(file);
			}
		}

		for (int i = 0; i < displayFileList.size(); i++) {
			System.out.println((i + 1) + ". " + displayFileList.get(i).getName());
		}

		Integer fileIndex1 = 0;
		Integer fileIndex2 = 0;
		System.out.println(Cons.R_N + "请从以下文件中选择需要比较的第一个文件: ");
		fileIndex1 = customerSelectFileIndex(displayFileList, null);

		System.out.println(Cons.R_N + "请从以下文件中选择需要比较的第二个文件: ");
		fileIndex2 = customerSelectFileIndex(displayFileList, fileIndex1);

		System.out.println("正在比较选中的两个文件： " + displayFileList.get(fileIndex1 - 1).getName() + ", "
				+ displayFileList.get(fileIndex2 - 1).getName() + " ...");

		compareSelectedXML(projectPath, displayFileList.get(fileIndex1 - 1), displayFileList.get(fileIndex2 - 1));

	}

	private static Integer customerSelectFileIndex(List<File> displayFileList, Integer firstIndex) throws IOException {
		System.out.print("输入序号 ");

		Integer fileIndex = null;
		BufferedReader br = null;
		try {
			br = new BufferedReader(new InputStreamReader(System.in));
			String strIndex = br.readLine();
			Pattern pattern = Pattern.compile("^[0-9]+$");
			Matcher isNum = pattern.matcher(strIndex);

			if (isNum.matches()) {
				fileIndex = Integer.valueOf(strIndex);

				if (fileIndex <= 0 || fileIndex > displayFileList.size()) {
					System.out.print("序号超出范围,  ");
					fileIndex = customerSelectFileIndex(displayFileList, firstIndex);

				} else if (firstIndex != null) {
					String suffix1 = displayFileList.get(firstIndex - 1).getName();
					suffix1 = suffix1.substring(suffix1.lastIndexOf("."));

					String suffix2 = displayFileList.get(fileIndex - 1).getName();
					suffix2 = suffix2.substring(suffix2.lastIndexOf("."));

					if (fileIndex.compareTo(firstIndex) == 0) {
						System.out.print("序号不能等于第一个 , ");
						fileIndex = customerSelectFileIndex(displayFileList, firstIndex);

					} else if (!StringUtils.equals(suffix1, suffix2)) {
						System.out.print("和第一个文件类型不一至, ");
						fileIndex = customerSelectFileIndex(displayFileList, firstIndex);
					}
				}

			} else {
				System.out.print("序号序号不是数字, ");
				fileIndex = customerSelectFileIndex(displayFileList, firstIndex);
			}

		} catch (NumberFormatException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();

		}

		return fileIndex;
	}

	private static void compareSelectedXML(String projectPath, File file1, File file2) throws DocumentException,
			IOException {
		BufferedWriter bw = null;
		FileInputStream fs1 = null;
		FileInputStream fs2 = null;
		try {
			bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(projectPath + "/compare_result.txt",
					false), "UTF-8"));

			SAXReader reader = new SAXReader();
			fs1 = new FileInputStream(file1);
			fs2 = new FileInputStream(file2);
			Document doc1 = reader.read(fs1);
			Document doc2 = reader.read(fs2);
			Element rootEle1 = doc1.getRootElement();
			Element rootEle2 = doc2.getRootElement();

			bw.write("1. " + file1.getName() + "比" + file2.getName() + ", 多的信息:" + Cons.R_N);
			bw.write("-------------------------------------------------------------------------------" + Cons.R_N);
			compareElement(rootEle1, doc2, rootEle1.getPath(), Cons.TAB, bw);

			bw.write(Cons.R_N + Cons.R_N + "2. " + file2.getName() + "比" + file1.getName() + ", 多的信息:" + Cons.R_N);
			bw.write("-------------------------------------------------------------------------------" + Cons.R_N);
			compareElement(rootEle2, doc1, rootEle1.getPath(), Cons.TAB, bw);

			bw.write(Cons.R_N + Cons.R_N + "3. " + file1.getName() + "与" + file2.getName() + ", 不同的属性值:" + Cons.R_N);
			bw.write("-------------------------------------------------------------------------------" + Cons.R_N);
			compareElementText(rootEle1, doc2, rootEle1.getPath(), Cons.TAB, bw);

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (bw != null) {
				bw.close();
			}
			if (fs1 != null) {
				fs1.close();
			}
			if (fs2 != null) {
				fs2.close();
			}
		}

	}

	private static void compareElement(Element element1, Document rootEle2, String xPath, String tab, BufferedWriter bw)
			throws Exception {
		if (element1.attribute("id") != null) {
			xPath = xPath + "[@id='" + element1.attributeValue("id") + "']";
		} else if (element1.attribute("name") != null) {
			xPath = xPath + "[@name='" + element1.attributeValue("name") + "']";
		} else if (element1.attribute("en") != null) {
			xPath = xPath + "[@w:en='" + element1.attributeValue("en") + "']";

		} else if (element1.attribute("TotalCode") != null) {
			xPath = xPath + "[@TotalCode='" + element1.attributeValue("TotalCode") + "']";
		} else if (element1.attribute("enName") != null) {
			xPath = xPath + "[@enName='" + element1.attributeValue("enName") + "']";
		} else if (element1.attribute("ID") != null) {
			xPath = xPath + "[@ID='" + element1.attributeValue("ID") + "']";
		} else if (element1.attribute("type") != null) {
			xPath = xPath + "[@type='" + element1.attributeValue("type") + "']";
		} else if (element1.attribute("Index") != null) {
			xPath = xPath + "[@Index='" + element1.attributeValue("Index") + "']";
		} else if (element1.attribute("Data") != null) {
			xPath = xPath + "[@Data='" + element1.attributeValue("Data") + "']";
		} else if (element1.attribute("Type") != null) {
			xPath = xPath + "[@Type='" + element1.attributeValue("Type") + "']";
		} else if (element1.attribute("Level") != null) {
			xPath = xPath + "[@Level='" + element1.attributeValue("Level") + "']";
		} else if (element1.attribute("value") != null) {
			xPath = xPath + "[@value='" + element1.attributeValue("value") + "']";
		}

		System.out.println("xPath=" + xPath);

		try {
			if (!element1.isRootElement()) {
				// 1. 取得对应节点
				Element element2 = (Element) rootEle2.selectSingleNode(xPath);

				if (element2 == null) {
					bw.write(tab + "+节点 " + xPath + Cons.R_N);
					return;
				}

				StringBuilder sb = new StringBuilder();

				List<Attribute> attrList = element1.attributes();
				for (Attribute attr1 : attrList) {
					Attribute attr2 = element2.attribute(attr1.getName());
					if (attr2 == null) {
						sb.append(tab + Cons.TAB + "+属性 " + "[@" + attr1.getName() + "] = \"" + attr1.getValue() + "\""
								+ Cons.R_N);
						continue;
					}
				}

				if (sb.length() > 0) {
					bw.write(tab + "在节点中 " + xPath + Cons.R_N);
					bw.write(sb.toString());
				}
			}

			Iterator<Element> eleIterator = element1.elementIterator();
			while (eleIterator.hasNext()) {
				Element next = eleIterator.next();
				String nextPath = next.getPath();
				nextPath = nextPath.substring(nextPath.lastIndexOf("/"));

				compareElement(next, rootEle2, (xPath + nextPath), Cons.TAB, bw);
			}

		} catch (Exception e) {
			System.out.println(element1.getPath());
			throw e;
		}

	}

	private static void compareElementText(Element element1, Document rootEle2, String xPath, String tab,
			BufferedWriter bw) throws Exception {
		if (element1.attribute("id") != null) {
			xPath = xPath + "[@id='" + element1.attributeValue("id") + "']";
		} else if (element1.attribute("name") != null) {
			xPath = xPath + "[@name='" + element1.attributeValue("name") + "']";
		} else if (element1.attribute("en") != null) {
			xPath = xPath + "[@w:en='" + element1.attributeValue("en") + "']";

		} else if (element1.attribute("TotalCode") != null) {
			xPath = xPath + "[@TotalCode='" + element1.attributeValue("TotalCode") + "']";
		} else if (element1.attribute("enName") != null) {
			xPath = xPath + "[@enName='" + element1.attributeValue("enName") + "']";
		} else if (element1.attribute("ID") != null) {
			xPath = xPath + "[@ID='" + element1.attributeValue("ID") + "']";
		} else if (element1.attribute("type") != null) {
			xPath = xPath + "[@type='" + element1.attributeValue("type") + "']";
		} else if (element1.attribute("Index") != null) {
			xPath = xPath + "[@Index='" + element1.attributeValue("Index") + "']";
		} else if (element1.attribute("Data") != null) {
			xPath = xPath + "[@Data='" + element1.attributeValue("Data") + "']";
		} else if (element1.attribute("Type") != null) {
			xPath = xPath + "[@Type='" + element1.attributeValue("Type") + "']";
		} else if (element1.attribute("Level") != null) {
			xPath = xPath + "[@Level='" + element1.attributeValue("Level") + "']";
		} else if (element1.attribute("value") != null) {
			xPath = xPath + "[@value='" + element1.attributeValue("value") + "']";
		}

		System.out.println("xPath=" + xPath);

		try {
			if (!element1.isRootElement()) {
				// 1. 取得对应节点
				Element element2 = (Element) rootEle2.selectSingleNode(xPath);

				if (element2 == null) {
					return;
				}

				StringBuilder sb = new StringBuilder();

				List<Attribute> attrList = element1.attributes();
				for (Attribute attr1 : attrList) {
					Attribute attr2 = element2.attribute(attr1.getName());
					if (attr2 != null) {

						if (!StringUtils.equals(attr1.getValue(), attr2.getValue())) {
							sb.append(tab + Cons.TAB + "属性[@" + attr2.getName() + "]" + ", 左边 = \"" + attr1.getValue()
									+ "\", 右边=\"" + attr2.getValue() + "\"" + Cons.R_N);
						}
					}
				}

				if (sb.length() > 0) {
					bw.write(tab + "在节点中 " + xPath + Cons.R_N);
					bw.write(sb.toString());
				}
			}

			Iterator<Element> eleIterator = element1.elementIterator();
			while (eleIterator.hasNext()) {
				Element next = eleIterator.next();
				String nextPath = next.getPath();
				nextPath = nextPath.substring(nextPath.lastIndexOf("/"));

				compareElementText(next, rootEle2, (xPath + nextPath), Cons.TAB, bw);
			}

		} catch (Exception e) {
			System.out.println(element1.getPath());
			throw e;
		}

	}

}
